package com.itrui.encrypted_transmission.Thread;

import com.itrui.encrypted_transmission.CodeUtils;
import com.itrui.encrypted_transmission.JOSNUtils;
import com.itrui.encrypted_transmission.MyFile;
import com.itrui.encrypted_transmission.SM2Utils;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPrivateKey;
import org.bouncycastle.jcajce.provider.asymmetric.ec.BCECPublicKey;
import org.bouncycastle.util.encoders.Hex;

import java.io.*;
import java.net.InetAddress;
import java.net.Socket;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.util.ArrayList;

public class Clients {
    private MyFile file;

    public Clients(MyFile file) {
        this.file = file;
    }

    public void clientRun() throws IOException {
        //连接服务端 (ip , 端口）
        System.out.println("-=-=-=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-");
        InetAddress localHost = InetAddress.getLocalHost();
        System.out.println("本机ip（服务端）：" + localHost.toString());
        //连接本机的 8888端口, 如果连接成功，返回Socket对象
        Socket socket = new Socket(localHost, 6666);
        System.out.println("客户端，连接端口:" + socket.getPort());

        //1、生成公钥和私钥
        String publicKeyHex = null;
        String privateKeyHex = null;
        KeyPair keyPair = SM2Utils.createECKeyPair();
        PublicKey publicKey = keyPair.getPublic();
        if (publicKey instanceof BCECPublicKey) {
            //获取65字节非压缩缩的十六进制公钥串(0x04)
            publicKeyHex = Hex.toHexString(((BCECPublicKey) publicKey).getQ().getEncoded(false));
            System.out.println("---->SM2公钥：" + publicKeyHex);
        }

        PrivateKey privateKey = keyPair.getPrivate();
        if (privateKey instanceof BCECPrivateKey) {
            //获取32字节十六进制私钥串
            privateKeyHex = ((BCECPrivateKey) privateKey).getD().toString(16);
            System.out.println("---->SM2私钥：" + privateKeyHex);
        }


        int len = 0;
        byte[] bytes = new byte[1024];
        DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
        dos.writeUTF(privateKeyHex);
        dos.flush();

        long startTime = System.currentTimeMillis();
        try {
            System.out.println(file.getName()+"正在发送...");
            //4、序列化对象并且加密
            String serialize = JOSNUtils.serialize(file);
            String encrypt = SM2Utils.encrypt(publicKeyHex, serialize);
            //5、序列化对象到临时文件（防止文件过大）
            toTemp(encrypt);
            FileInputStream fis = new FileInputStream("D:\\RuiProject\\temp\\temp.txt");
            while ((len = fis.read(bytes)) != -1) {
                dos.write(bytes, 0, len);
            }

        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        socket.shutdownOutput();

        BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));
        String msg = br.readLine();
        System.out.println("来自服务器的消息：" + msg);
        System.out.println("耗时：" + (System.currentTimeMillis() - startTime) + "ms");

        dos.flush();

        //7、关闭流
        dos.close();
        socket.close();

    }

    /**
     * 序列化的对象写入临时文件
     *
     * @param data
     */
    public void toTemp(String data) {
        try {
            FileOutputStream fos = new FileOutputStream("D:\\RuiProject\\temp\\temp.txt");
            fos.write(data.getBytes());
            fos.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}
